package com.lzh.file.store;

import com.lzh.runke.core.web_base.constant.StringConstant;
import com.lzh.runke.core.web_base.helper.UUIDHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;

/**
 * FTP 存储实现
 *
 * @author xie
 */
@Slf4j
@Component
public class FileStoreFtp implements FileStoreApi {

    protected static final String PATH_SEPARATOR = "/";

    @Resource
    private ObjectFactory<FileObject> ftpRootObjectFactory;

    public FileObject getFtpRoot() {
        return this.ftpRootObjectFactory.getObject();
    }

    /**
     * 保存文件
     *
     * @param file 文件
     * @return filename 自动生成的UUID文件名
     */
    @Override
    public String save(File file) {
        Assert.notNull(file, "参数file不能为空");
        try {
            String extension = FilenameUtils.getExtension(file.getName());
            return this.save(new FileInputStream(file), extension);
        } catch (IOException e) {
            log.error("保存文件异常: ", e);
            return null;
        }
    }

    /**
     * 保存文件
     *
     * @param file 文件
     * @return filename 自动生成的UUID文件名
     */
    @Override
    public String save(MultipartFile file) {
        Assert.notNull(file, "参数file不能为空");
        try {
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            return this.save(file.getInputStream(), extension);
        } catch (IOException e) {
            log.error("保存文件异常: ", e);
            return null;
        }
    }

    /**
     * 保存文件
     *
     * @param stream    文件流
     * @param extension 文件扩展名
     * @see com.rkinf.framework.file.FileConstant .FILE_EXTENSION_*
     */
    @Override
    public String save(InputStream stream, String extension) {
        Assert.notNull(stream, "参数stream不能为空");
        Assert.notNull(extension, "参数extension不能为空");
        // 生成UUID文件名 无后缀
        StringBuilder filename = new StringBuilder(UUIDHelper.randomUUID());
        // 生成完整文件名
        filename.append(StringConstant.DOT).append(extension);
        // 生成文件目录
        String fullPath = buildFullPath(filename.toString()).toString();
        FileObject fileRoot = getFtpRoot();

        OutputStream outputStream = null;
        try {
            FileObject fileObject = fileRoot.resolveFile(fullPath + "/" + filename);
            outputStream = fileObject.getContent().getOutputStream();

            IOUtils.copy(stream, outputStream);
            outputStream.flush();

            return filename.toString();
        } catch (IOException e) {
            log.error("保存文件异常: ", e);
            return null;
        } finally {
            close(stream);
            close(outputStream);
        }
    }

    /**
     * 根据文件名 删除已上传文件
     *
     * @param filename
     * @return
     */
    @Override
    public boolean deleteFile(String filename) {
        Assert.notNull(filename, "参数filename不能为空");

        FileObject ftpRoot = getFtpRoot();
        try {
            FileObject fileObject = ftpRoot.resolveFile(buildFullPath(filename).append("/").append(filename).toString());
            return fileObject.delete();
        } catch (FileSystemException e) {
            log.error("删除文件异常: ", e);
            return false;
        } catch (IOException e) {
            log.error("删除文件异常: ", e);
            return false;
        }
    }

    /**
     * 根据文件名 删除已上传文件
     *
     * @param filenames []
     * @return
     */
    @Override
    public boolean deleteFile(String[] filenames) {
        Assert.notNull(filenames, "参数filenames不能为空");

        FileObject ftpRoot = getFtpRoot();
        try {
            for (String filename : filenames) {
                FileObject fileObject = ftpRoot.resolveFile(buildFullPath(filename).append("/").append(filename).toString());
                fileObject.delete();
            }
            return true;
        } catch (FileSystemException e) {
            log.error("删除文件异常: ", e);
            return false;
        } catch (IOException e) {
            log.error("删除文件异常: ", e);
            return false;
        }
    }

    /**
     * 文件下载
     *
     * @param filename
     * @return
     * @throws IOException
     */
    @Override
    public byte[] loadFileBytes(String filename) {
        Assert.notNull(filename, "参数filename不能为空");

        FileObject ftpRoot = getFtpRoot();
        try {
            FileObject fileObject = ftpRoot.resolveFile(buildFullPath(filename).append("/").append(filename).toString());
            return fileObject.getContent().getByteArray();
        } catch (FileSystemException e) {
            log.error("删除文件异常: ", e);
            return null;
        } catch (IOException e) {
            log.error("删除文件异常: ", e);
            return null;
        }
    }

    /**
     * 读取本地文件
     *
     * @param filename
     * @return
     */
    public File loadFile(String filename) {
        return null;
    }

    /**
     * 根据uuid文件名分目录
     *
     * @param uuidName
     */
    @Override
    public StringBuilder buildFullPath(String uuidName) {
        Assert.hasText(uuidName, "参数uuidName不能为空");

        StringBuilder pathBuilder = new StringBuilder(PATH_SEPARATOR);

        return pathBuilder.append(uuidName.substring(0, 2).toLowerCase())
                .append(PATH_SEPARATOR).append(uuidName.substring(2, 4).toLowerCase())
                .append(PATH_SEPARATOR).append(uuidName.substring(4, 6).toLowerCase())
                .append(PATH_SEPARATOR).append(uuidName.substring(6, 8).toLowerCase());
    }

    private void close(Closeable closeable) {
        try {
            IOUtils.close(closeable);
        } catch (IOException e) {
            log.error("关闭资源异常: ", e);
        }
    }
}
